// Stream 封装
const fs = require('fs');
const EventEmitter = require('events');
class ReadStream extends EventEmitter {
    constructor(path, options = {}) {
        // 继承一定要调用父亲构造
        super();
        this.path = path;
        // 读写标记
        this.flags = options.flags || 'r';
        this.mode = options.mode || 0o666;
        this.autoClose = options.autoClose || true;
        this.start = options.start || 0;
        this.end = options.end || 0;
        this.highWaterMark = options.highWaterMark || 64 * 1024;

        // 记录当前的状态 流动，还是暂停
        this.state = false;
        // 每次读取文件的偏移量
        this.pos = this.start;
        // 在new的时候，会自动打开文件
        this.open();

        // 监听是否要真的读取文件
        this.on('newListener', (eventName) => {
            if ('data' == eventName) {
                this.state = true;
                // 开始读取文件
                this.read();
            }
        })
    }
    // 打开文件
    open() {
        fs.open(this.path, this.flags, this.mode, (err, fd) => {
            if (err) return this.emit('error', err);
            this.fd = fd;
            this.emit('open', fd);
        })
    }
    // 读取文件
    read() {
        if (typeof this.fd !== 'number') {
            // 说明文件还没有打开。
            // 为什么这么写？因为read是同步任务，而open文件是异步任务，所以这里会先执行。
            // 所以拿不到是正常的
            return this.once('open', this.read);
        } else {
            // 正常读取就好了
            let buffer = Buffer.alloc(this.highWaterMark);
            // 让end生效。
            let perReadSize = this.end? Math.min(this.end - this.pos + 1, this.highWaterMark):this.highWaterMark;
            fs.read(this.fd, buffer, 0, perReadSize, this.pos, (err, bytesRead) => {
                if (err) return this.emit('error', err);

                if (bytesRead !== 0) {
                    // 说明有读取到,把buffer返回回去
                    this.emit('data', buffer);
                    this.pos += bytesRead;
                    if(this.state){
                        this.read();
                    }
                } else {
                    this.emit('end');
                    // 关闭文件
                    this.close();
                }
            });
        }
    }
    // 暂停
    pause(){
        this.state = false;
    };
    // 继续
    resume(){
        this.state = true;
        this.read();
    }
    // 关闭文件
    close() {
        fs.close(this.fd, () => {
            this.emit('close');
        })
    }
}

module.exports = ReadStream;